/*
 * Powered By XY
 * Since 2020
 */

package com.xy.biz.xd.service.impl;

import java.sql.ResultSet;
import java.time.LocalDateTime;
import java.util.*;

import com.xy.biz.fd.client.DocumentClient;
import com.xy.biz.fd.client.DocumentCodePoolClient;
import com.xy.biz.fd.client.DocumentCodeRuleClient;
import com.xy.biz.fd.domain.req.SaveDocumentCodePoolRequest;
import com.xy.biz.fd.domain.req.document.SaveDocumentRequest;
import com.xy.biz.fd.domain.req.documentCode.GetDocumentCodeRuleRequest;
import com.xy.biz.fd.domain.resp.GetDocumentCodeRuleResponse1;
import com.xy.biz.mc.client.MessagePushClient;
import com.xy.biz.mc.domain.Message;
import com.xy.biz.mc.domain.consts.MessageTypeConstant;
import com.xy.biz.mc.domain.req.MessagePushRequest;
import com.xy.biz.xd.domain.bo.DocumentFlowBO;
import com.xy.biz.xd.domain.bo.DocumentFlowHandleBO;
import com.xy.biz.xd.domain.converter.DocumentFlowCancelRequestFlowConverter;
import com.xy.biz.xd.domain.req.DocumentFlowCancelRequestFlowRequest;
import com.xy.biz.xd.domain.req.SaveDocumentFlowCancelRequestFlowRequest;
import com.xy.biz.xd.manager.DocumentFlowHandleManager;
import com.xy.biz.xd.manager.DocumentFlowManager;
import com.xy.lang.util.ResultUtils;
import com.xy.tool.context.UserContextHolder;
import com.xy.tool.gid.service.GidService;
import com.xy.tool.json.JsonUtils;
import org.activiti.engine.task.Task;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.xy.lang.domain.Result;
import com.xy.biz.xd.domain.bo.DocumentFlowCancelRequestFlowBO;
import com.xy.biz.xd.domain.query.DocumentFlowCancelRequestFlowQuery;
import com.xy.biz.xd.service.DocumentFlowCancelRequestFlowService;
import com.xy.biz.xd.manager.DocumentFlowCancelRequestFlowManager;
import org.springframework.util.CollectionUtils;

import static com.xy.biz.xd.domain.bo.DocumentFlowConstants.*;

/**
 *
 *
 * @author zgy
 * @date 2021-6-17
 */
@Service
public class DocumentFlowCancelRequestFlowServiceImpl implements DocumentFlowCancelRequestFlowService {

    @Autowired
    private DocumentFlowCancelRequestFlowManager documentFlowCancelRequestFlowManager;
    @Autowired
    private GidService gidService;
    @Autowired
    private DocumentClient documentClient;
    @Autowired
    private MessagePushClient messagePushClient;
    @Autowired
    private DocumentFlowManager documentFlowManager;
    @Autowired
    private DocumentCodeRuleClient documentCodeRuleClient;
    @Autowired
    private DocumentCodePoolClient documentCodePoolClient;
    @Autowired
    private DocumentFlowHandleManager documentFlowHandleManager;
    @Autowired
    private DocumentFlowServiceSupport documentFlowServiceSupport;

    @Override
    public Result<?> saveDocumentFlowCancelRequestFlow(SaveDocumentFlowCancelRequestFlowRequest request) {
        DocumentFlowCancelRequestFlowBO documentFlowCancelRequestFlowBO = DocumentFlowCancelRequestFlowConverter.toBO(request);
        buildDocumentFlowCancelRequestFlowBO(documentFlowCancelRequestFlowBO);
        DocumentFlowCancelRequestFlowBO documentFlowCancelRequest = documentFlowCancelRequestFlowManager.getDocumentFlowCancelRequestFlowByDocumentFlowId(documentFlowCancelRequestFlowBO.getDocumentFlowId());
        int affectedRows = 0;
        if (documentFlowCancelRequest == null) {
            Task task = documentFlowServiceSupport.startFirstTaskOfCancelRequest(documentFlowCancelRequestFlowBO, PROCESS_CANCEL_REQUEST, documentFlowCancelRequestFlowBO.getDocumentHandlerUserId());
            documentFlowCancelRequestFlowBO.setForeignKey(task.getProcessInstanceId());

            affectedRows = documentFlowCancelRequestFlowManager.saveDocumentFlowCancelRequestFlow(documentFlowCancelRequestFlowBO);
        } else {
            Task currentTask = documentFlowServiceSupport.getCurrentTask(documentFlowCancelRequest);

            if (currentTask != null) {
                return Result.fail("", "此流程已处于取消申请状态中，请勿重复申请！");
            }
            Task task = documentFlowServiceSupport.startFirstTaskOfCancelRequest(documentFlowCancelRequestFlowBO, PROCESS_CANCEL_REQUEST, documentFlowCancelRequestFlowBO.getDocumentHandlerUserId());
            documentFlowCancelRequest.setForeignKey(task.getProcessInstanceId());
            documentFlowCancelRequest.setStatusFlag(DocumentFlowCancelRequestFlowBO.AUDIT);
            documentFlowCancelRequest.setReason(request.getReason());
            documentFlowCancelRequest.setDocumentHandlerUserId(request.getDocumentHandlerUserId());
            documentFlowCancelRequest.setUpdateTime(LocalDateTime.now());
            affectedRows = documentFlowCancelRequestFlowManager.updateDocumentFlowCancelRequestFlow(documentFlowCancelRequest);
        }
        if (affectedRows > 0) {
            //定义消息内容
            Message build = Message.builder()
                    .type(MessageTypeConstant.TYPE_FLOW)
                    .data(1)
                    .path(MessageTypeConstant.FLOW_LIST)
                    .remark("取消申请流程-申请")
                    .build();
            //发送消息
            messagePushClient.send(MessagePushRequest.builder()
                    .data(JsonUtils.toJson(build).getBytes())
                    .dataType(0)
                    .expiredSeconds(0L)
                    .toId(documentFlowCancelRequestFlowBO.getDocumentHandlerUserId())
                    .offlineFlag(true).build());
        }
        return Result.success();
    }

    /**
     * 审核
     *
     * @param request
     */
    @Override
    public Result<?> auditDocumentFlowCancelRequestFlow(DocumentFlowCancelRequestFlowRequest request) {
        LocalDateTime now = LocalDateTime.now();
        DocumentFlowCancelRequestFlowBO documentFlowCancelRequestFlowBO = documentFlowCancelRequestFlowManager.getDocumentFlowCancelRequestFlowByDocumentFlowId(request.getDocumentFlowId());
        DocumentFlowBO documentFlowBO = documentFlowManager.getDocumentFlow(request.getDocumentFlowId());
        if(documentFlowBO == null){
            return Result.fail("","被取消的流程不存在！");
        }
        //同意
        if (Objects.equals(request.getResult(), HANDLE_RESULT_ACCEPT)) {
            build(documentFlowCancelRequestFlowBO, UserContextHolder.getUserId(), PHASE_AGREE_CANCEL, HANDLE_RESULT_ACCEPT, request.getReason());
            documentFlowServiceSupport.finish(documentFlowBO);
            documentFlowCancelRequestFlowBO.setStatusFlag(DocumentFlowCancelRequestFlowBO.AGREE);
            documentFlowBO.setPhase(PHASE_CANCEL);
            documentFlowManager.updateDocumentFlow(documentFlowBO);
            if (documentFlowBO.getDocumentFlowId() != null) {
                //流程文件解锁
                documentClient.updateDocument(SaveDocumentRequest.builder().documentFlowLock(false).documentId(documentFlowBO.getDocumentId()).build());
            }
//            //终止的流程需要回收文件编码
//            GetDocumentCodeRuleResponse1 response1 = ResultUtils.get(documentCodeRuleClient.getCodeInfo(GetDocumentCodeRuleRequest.builder().code(documentFlowBO.getDocumentCode()).build()));
//            if (response1 == null) {
//                return Result.fail();
//            }
            SaveDocumentCodePoolRequest req = SaveDocumentCodePoolRequest.builder()
                    .documentCode(documentFlowBO.getDocumentCode())
                    .reuseFlag(true)
                    .updateTime(now).build();
            ResultUtils.get(documentCodePoolClient.updateDocumentCodePool(req));
        } else {
            //不同意
            build(documentFlowCancelRequestFlowBO, UserContextHolder.getUserId(), PHASE_REJECT_CANCEL, HANDLE_RESULT_REJECT, request.getReason());
            documentFlowCancelRequestFlowBO.setStatusFlag(DocumentFlowCancelRequestFlowBO.DISAGREE);
        }
        documentFlowServiceSupport.finishLastTaskOfCancelRequest(documentFlowCancelRequestFlowBO);
        documentFlowCancelRequestFlowBO.setUpdateTime(now);
        int row = documentFlowCancelRequestFlowManager.updateDocumentFlowCancelRequestFlow(documentFlowCancelRequestFlowBO);
        if (row > 0) {
            //发送消息
            //通过
            if (Objects.equals(request.getResult(), HANDLE_RESULT_ACCEPT)) {
                //发送消息
                //定义消息内容
                Message message = Message.builder()
                        .type(MessageTypeConstant.TYPE_FLOW)
                        .data(1)
                        .remark("取消申请流程-审批通过\n" + request.getReason())
                        .path(MessageTypeConstant.FLOW_LIST)
                        .build();
                sendMessage(message, documentFlowCancelRequestFlowBO.getCreateUserId());
            } else {
                //拒绝通过
                Message message = Message.builder()
                        .type(MessageTypeConstant.TYPE_FLOW)
                        .data(1)
                        .remark("取消申请流程-审批不通过\n" + request.getReason())
                        .path(MessageTypeConstant.FLOW_LIST)
                        .build();
                sendMessage(message, documentFlowCancelRequestFlowBO.getCreateUserId());
            }
        }
        return Result.success();
    }

    @Override
    public Result<?> saveAllDocumentFlowCancelRequestFlow(Collection<DocumentFlowCancelRequestFlowBO> collection) {
        int affectedRows = documentFlowCancelRequestFlowManager.saveAllDocumentFlowCancelRequestFlow(collection);
        if (affectedRows > 0) {
            return Result.success();
        }
        return Result.ofErrorRowsAffected();
    }

    @Override
    public Result<?> updateDocumentFlowCancelRequestFlow(DocumentFlowCancelRequestFlowBO documentFlowCancelRequestFlowBO) {
        int affectedRows = documentFlowCancelRequestFlowManager.updateDocumentFlowCancelRequestFlow(documentFlowCancelRequestFlowBO);
        if (affectedRows > 0) {
            return Result.success();
        }
        return Result.ofErrorRowsAffected();
    }

    @Override
    public Result<?> deleteDocumentFlowCancelRequestFlow(Long documentFlowCancelRequestFlowId) {
        int affectedRows = documentFlowCancelRequestFlowManager.deleteDocumentFlowCancelRequestFlow(documentFlowCancelRequestFlowId);
        if (affectedRows > 0) {
            return Result.success();
        }
        return Result.ofErrorRowsAffected();
    }

    @Override
    public DocumentFlowCancelRequestFlowBO getDocumentFlowCancelRequestFlow(Long documentFlowCancelRequestFlowId) {
        return documentFlowCancelRequestFlowManager.getDocumentFlowCancelRequestFlow(documentFlowCancelRequestFlowId);
    }

    @Override
    public List<DocumentFlowCancelRequestFlowBO> listDocumentFlowCancelRequestFlowById(Collection<Long> collection) {
        return documentFlowCancelRequestFlowManager.listDocumentFlowCancelRequestFlowById(collection);
    }

    @Override
    public List<DocumentFlowCancelRequestFlowBO> listDocumentFlowCancelRequestFlow(DocumentFlowCancelRequestFlowQuery query) {
        return documentFlowCancelRequestFlowManager.listDocumentFlowCancelRequestFlow(query);
    }

    @Override
    public int countDocumentFlowCancelRequestFlow(DocumentFlowCancelRequestFlowQuery query) {
        return documentFlowCancelRequestFlowManager.countDocumentFlowCancelRequestFlow(query);
    }


    private void buildDocumentFlowCancelRequestFlowBO(DocumentFlowCancelRequestFlowBO documentFlowCancelRequestFlowBO) {
        LocalDateTime now = LocalDateTime.now();
        documentFlowCancelRequestFlowBO.setCancelRequestFlowId(gidService.generate());
        documentFlowCancelRequestFlowBO.setCreateUserId(UserContextHolder.getUserId());
        documentFlowCancelRequestFlowBO.setFlowType(FLOW_TYPE_CANCEL_REQUEST);
        documentFlowCancelRequestFlowBO.setTenantId(UserContextHolder.getTenantId());
        documentFlowCancelRequestFlowBO.setCreateTime(now);
        documentFlowCancelRequestFlowBO.setUpdateTime(now);
        documentFlowCancelRequestFlowBO.setStatusFlag(DocumentFlowCancelRequestFlowBO.AUDIT);
        documentFlowCancelRequestFlowBO.setDeleteFlag(false);
        //将取消申请操作记录进Handle表
        build(documentFlowCancelRequestFlowBO, UserContextHolder.getUserId(), PHASE_CANCEL, HANDLE_RESULT_CANCEL, documentFlowCancelRequestFlowBO.getReason());

    }

    private void build(DocumentFlowCancelRequestFlowBO documentFlowCancelRequestFlowBO,
                       Long handleUserId,
                       String phase,
                       int result,
                       String opinion) {
        DocumentFlowBO documentFlow = documentFlowManager.getDocumentFlow(documentFlowCancelRequestFlowBO.getDocumentFlowId());
        DocumentFlowHandleBO documentFlowHandleBO = new DocumentFlowHandleBO();
        documentFlowHandleBO.setDocumentFlowId(documentFlowCancelRequestFlowBO.getCancelRequestFlowId());
        documentFlowHandleBO.setPhase(phase);
        documentFlowHandleBO.setResult(result);
        documentFlowHandleBO.setOpinion(opinion);
        documentFlowHandleBO.setHandleUserId(handleUserId);
        documentFlowHandleBO.setHandleUserGroupId(UserContextHolder.getUserGroupId());
        documentFlowHandleBO.setFlowType(documentFlowCancelRequestFlowBO.getFlowType());
        documentFlowHandleBO.setDocumentCode(documentFlow.getDocumentCode());
        documentFlowHandleBO.setTenantId(UserContextHolder.getTenantId());
        documentFlowHandleBO.setCreateUserId(UserContextHolder.getUserId());
        documentFlowHandleBO.setCreateTime(LocalDateTime.now());
        documentFlowHandleBO.setUpdateTime(LocalDateTime.now());
        List<DocumentFlowHandleBO> documentFlowHandleBOS = new ArrayList<>();
        documentFlowHandleBOS.add(documentFlowHandleBO);
        documentFlowHandleManager.saveAllDocumentFlowHandle(documentFlowHandleBOS);
    }

    /**
     * 发送信息
     * @param message
     * @param toId
     */
    protected void sendMessage(Message message, Long toId) {
        messagePushClient.send(MessagePushRequest.builder()
                .data(JsonUtils.toJson(message).getBytes())
                .dataType(0)
                .expiredSeconds(0L)
                .toId(toId)
                .offlineFlag(true).build());
    }
}
